package com.caochenlei.filter;

import com.caochenlei.domain.Payload;
import com.caochenlei.domain.SysUser;
import com.caochenlei.prop.RsaKeyProperties;
import com.caochenlei.utils.JwtUtils;
import com.caochenlei.utils.ResponseUtils;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 验证过滤器
 *
 * @author CaoChenLei
 */
@Slf4j
public class JwtVerificationFilter extends BasicAuthenticationFilter {
    private RsaKeyProperties prop;

    public JwtVerificationFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) {
        super(authenticationManager);
        this.prop = prop;
    }

    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            String header = request.getHeader("Authorization");
            if (header == null || !header.startsWith("Bearer ")) {
                //如果token的格式错误，则提示用户非法登录
                ResponseUtils.write(response, false, "用户非法登录！");
                log.info("用户非法登录！");
            } else {
                //如果token的格式正确，则先要获取到token
                String token = header.replace("Bearer ", "");
                //使用公钥进行解密然后来验证token是否正确
                try {
                    Payload<SysUser> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), SysUser.class);
                    SysUser sysUser = payload.getUserInfo();
                    if (sysUser != null) {
                        UsernamePasswordAuthenticationToken authResult = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), null, sysUser.getAuthorities());
                        SecurityContextHolder.getContext().setAuthentication(authResult);
                        chain.doFilter(request, response);
                    } else {
                        ResponseUtils.write(response, false, "用户验证失败！");
                        log.info("用户验证失败！");
                    }
                } catch (SignatureException | MalformedJwtException e) {
                    ResponseUtils.write(response, false, "用户签名伪造！");
                    log.info("用户签名伪造！");
                }
            }
        } catch (ExpiredJwtException e) {
            ResponseUtils.write(response, false, "用户会话超时，请您重新登录！");
            log.info("用户会话超时，请您重新登录！");
        }
    }
}